package zmee.bid.formplugin;

import kd.bos.dataentity.entity.DataEntityBase;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.dataentity.resource.ResManager;
import kd.bos.dataentity.utils.StringUtils;
import kd.bos.entity.datamodel.IDataModel;
import kd.bos.entity.datamodel.events.ChangeData;
import kd.bos.entity.datamodel.events.PropertyChangedArgs;
import kd.bos.form.CloseCallBack;
import kd.bos.form.control.EntryGrid;
import kd.bos.form.events.AfterDoOperationEventArgs;
import kd.bos.form.events.BeforeDoOperationEventArgs;
import kd.bos.form.events.ClosedCallBackEvent;
import kd.bos.form.field.BasedataEdit;
import kd.bos.form.field.RefBillEdit;
import kd.bos.form.field.events.AfterBindingDataEvent;
import kd.bos.form.field.events.BasedataEditListener;
import kd.bos.form.field.events.BeforeF7SelectEvent;
import kd.bos.form.field.events.BeforeF7SelectListener;
import kd.bos.form.operate.FormOperate;
import kd.bos.form.plugin.AbstractFormPlugin;
import kd.bos.list.ListShowParameter;
import kd.bos.logging.Log;
import kd.bos.logging.LogFactory;
import kd.bos.orm.query.QCP;
import kd.bos.orm.query.QFilter;
import kd.bos.servicehelper.BusinessDataServiceHelper;
import kd.bos.servicehelper.QueryServiceHelper;
import kd.bos.servicehelper.operation.SaveServiceHelper;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author lijiawang
 * @Date 2022/11/21 14:11
 * @Description:招标立项申请单
 */
public class SrcDemandFormPlugin extends AbstractFormPlugin implements BeforeF7SelectListener, BasedataEditListener {
    private static final Log logger = LogFactory.getLog(SrcDemandFormPlugin.class);

    @Override
    public void registerListener(EventObject e) {
        BasedataEdit listingBudgetItem = this.getView().getControl("approvalbudget");
        RefBillEdit pro_approval = this.getView().getControl("pro_approval");
        listingBudgetItem.addBeforeF7SelectListener(this);
        pro_approval.addBasedataEditListener(this);
        pro_approval.addBeforeF7SelectListener(this);
    }


    @Override
    public void propertyChanged(PropertyChangedArgs e) {
        IDataModel model = this.getModel();
        String name = e.getProperty().getName();
        ChangeData[] changeSet = e.getChangeSet();
        ChangeData data = changeSet[0];
        Object object = data.getNewValue();
        int rowIndex = data.getRowIndex();
        if ("pro_approval".equals(name)) {
            //项目支出预算
            if (object != null) {
                DynamicObject Obj = (DynamicObject) object;
                DynamicObject outbudget = BusinessDataServiceHelper.loadSingle("pmas_outbudget", "id,zmee_textfield,totalamount",
                        new QFilter("id", QCP.equals, Obj.getPkValue().toString()).toArray());
                //项目总预算
                model.setValue("projectbudget", outbudget.getBigDecimal("zmee_textfield"));
                //项目年度预算
                model.setValue("projectyearbudget", outbudget.getBigDecimal("totalamount"));

                model.setValue("remaining", 0);
            }
        }

        //项目预算项
        if ("approvalbudget".equals(name)) {
            if (object == null) {
                logger.info("预算项目为空");
                model.setValue("budgebalance", 0, rowIndex);
                model.setValue("budgetmoney", 0, rowIndex);
            }
            DynamicObject dat = (DynamicObject) data.getNewValue();

            //项目支出预算
            DynamicObject approval = (DynamicObject) this.getModel().getValue("pro_approval");
            DynamicObject business = BusinessDataServiceHelper.loadSingle(approval.getPkValue(), approval.getDynamicObjectType().getName());
            String group = business.getString("group.number");
            DynamicObjectCollection treeentryentity = business.getDynamicObjectCollection("treeentryentity");
            logger.info("预算分录size:" + treeentryentity.size());
            DynamicObject approvals = BusinessDataServiceHelper.loadSingle(dat.getPkValue(), dat.getDynamicObjectType().getName());
            String budgetId = approvals.getPkValue().toString();
            logger.info("group " + group);
            switch (group) {
                case "10201":
                case "10301":
                case "10302":
                case "10303":
                case "10304":
                case "10305":
                case "10401":
                case "10601":
                    for (DynamicObject tre : treeentryentity) {
                        if (budgetId.equals(tre.getDynamicObject("projectbudgetitem").getPkValue().toString())) {
                            BigDecimal budgetamoney = tre.getBigDecimal("budgetamoney");
                            BigDecimal amount = (BigDecimal) model.getValue("amount");
                            BigDecimal subtract = budgetamoney.subtract(amount);
                            logger.info("项目预算金额1 ：" + subtract);
                            model.setValue("budgebalance", subtract, rowIndex);

                        }
                    }
                    break;
                default:
                    for (DynamicObject tre : treeentryentity) {
                        if (budgetId.equals(tre.getDynamicObject("projectbudgetitem").getPkValue().toString())) {
                            BigDecimal budgetamoney = tre.getBigDecimal("budgetamoney");
                            BigDecimal taxamount = (BigDecimal) model.getValue("taxamount");
                            BigDecimal subtract = budgetamoney.subtract(taxamount);
                            logger.info("项目预算金额2 ：" + subtract);
                            model.setValue("budgebalance", subtract, rowIndex);
                        }
                    }

                    break;
            }

            DynamicObjectCollection entryentitys = model.getEntryEntity("entryentity");
            Map<String, Map<String, BigDecimal>> maps = entyNumMoney(entryentitys, dat, treeentryentity);
            BigDecimal remaining = new BigDecimal("0");//余额

            for (String key : maps.keySet()) {
                Map<String, BigDecimal> decimalMap = maps.get(key);
                //余额
                BigDecimal bigRemaining = decimalMap.get("remaining");
                remaining = remaining.add(bigRemaining);
            }
            model.setValue("summoney", remaining);

        }

        //未税金额
        if ("amount".equals(name)) {
            BigDecimal big = (BigDecimal) data.getNewValue();//改变的值
            DynamicObjectCollection entryentity = this.getModel().getEntryEntity("entryentity");
            DynamicObject row = entryentity.get(rowIndex);
            BigDecimal budgetmoney = row.getBigDecimal("budgetmoney");
            DynamicObject approval = (DynamicObject) this.getModel().getValue("pro_approval");
            DynamicObject business = BusinessDataServiceHelper.loadSingle(approval.getPkValue(), approval.getDynamicObjectType().getName());
            String group = business.getString("group.number");
            BigDecimal bigDecimal = new BigDecimal("0");
            switch (group) {
                case "10201":
                case "10301":
                case "10302":
                case "10303":
                case "10304":
                case "10305":
                case "10401":
                case "10601":
                    model.setValue("budgebalance", budgetmoney.subtract(big), rowIndex);
                    bigDecimal = entyConutTaxamount(entryentity, "amount");
                    break;
                default:
                    bigDecimal = entyConutTaxamount(entryentity, "taxamount");
                    break;
            }
            this.getModel().setValue("money", bigDecimal);
        }

        //价税合计
        if ("taxamount".equals(name)) {
            BigDecimal big = (BigDecimal) data.getNewValue();//改变的值

            //获取分录
            DynamicObjectCollection entryentity = this.getModel().getEntryEntity("entryentity");
            DynamicObject row = entryentity.get(rowIndex);
            BigDecimal budgetmoney = row.getBigDecimal("budgetmoney");


            model.setValue("zmee_money", entyConutTaxamount(entryentity, "taxamount"));
            DynamicObject approval = (DynamicObject) this.getModel().getValue("pro_approval");
            DynamicObject business = BusinessDataServiceHelper.loadSingle(approval.getPkValue(), approval.getDynamicObjectType().getName());
            String group = business.getString("group.number");
            BigDecimal bigDecimal = new BigDecimal("0");
            switch (group) {
                case "10201":
                case "10301":
                case "10302":
                case "10303":
                case "10304":
                case "10305":
                case "10401":
                case "10601":
                    bigDecimal = entyConutTaxamount(entryentity, "amount");
                    break;
                default:
                    model.setValue("budgebalance", budgetmoney.subtract(big), rowIndex);
                    bigDecimal = entyConutTaxamount(entryentity, "taxamount");
                    break;
            }
            this.getModel().setValue("money", bigDecimal);
        }

    }

    @Override
    public void afterDoOperation(AfterDoOperationEventArgs args) {
        String operateKey = args.getOperateKey();
        if ("deleteentrynotyear".equals(operateKey)) {
            DynamicObjectCollection entryentitys = this.getModel().getEntryEntity("entryentity");
            DynamicObject approval = (DynamicObject) this.getModel().getValue("pro_approval");
            DynamicObject business = BusinessDataServiceHelper.loadSingle(approval.getPkValue(), approval.getDynamicObjectType().getName());
            DynamicObjectCollection treeentryentity = business.getDynamicObjectCollection("treeentryentity");
            Map<String, Map<String, BigDecimal>> maps = entyNumMoney(entryentitys, null, treeentryentity);
            BigDecimal remaining = new BigDecimal("0");//余额
            for (String keys : maps.keySet()) {
                //余额
                Map<String, BigDecimal> decimalMap = maps.get(keys);
                BigDecimal bigRemaining = decimalMap.get("remaining");
                remaining = remaining.add(bigRemaining);
            }
            this.getModel().setValue("summoney", remaining);
        }

        if ("save".equals(operateKey)) {
            boolean box = (boolean) this.getModel().getValue("checkbox");
            if (!box) {
                //获取分录
                DynamicObjectCollection entryentity = this.getModel().getEntryEntity("entryentity");
                this.getModel().setValue("zmee_money", entyConutTaxamount(entryentity, "taxamount"));
                DynamicObject approval = (DynamicObject) this.getModel().getValue("pro_approval");
                DynamicObject business = BusinessDataServiceHelper.loadSingle(approval.getPkValue(),
                        approval.getDynamicObjectType().getName());
                String group = business.getString("group.number");
                String parent = business.getString("group.parent.number");
                BigDecimal bigDecimal = new BigDecimal("0");
                if (!"106".equals(parent)) {
                    switch (group) {
                        case "10201":
                        case "10301":
                        case "10302":
                        case "10303":
                        case "10304":
                        case "10305":
                        case "10401":
                        case "10601":
                            bigDecimal = entyConutTaxamount(entryentity, "amount");
                            break;
                        default:
                            bigDecimal = entyConutTaxamount(entryentity, "taxamount");
                            break;
                    }
                } else {
                    bigDecimal = entyConutTaxamount(entryentity, "amount");
                }
                this.getModel().setValue("money", bigDecimal);
            }
        }
    }

    @Override
    public void beforeDoOperation(BeforeDoOperationEventArgs args) {
        FormOperate entry = (FormOperate) args.getSource();
        String operateKey = entry.getOperateKey();
        if ("deleteentrynotyear".equals(operateKey)) {
            EntryGrid entryGrid = this.getControl("entryentity");
            int[] selectRows = entryGrid.getSelectRows();
            this.getModel().deleteEntryRows("entryentity", selectRows);
        }
        //审核 or 反审核 作废
        if ("audit".equals(operateKey) || "unaudit".equals(operateKey) || "invalid".equals(operateKey)) {
            boolean checkbox = (boolean) getModel().getValue("checkbox");
            if (!checkbox) {
                DynamicObject approval = (DynamicObject) this.getModel().getValue("pro_approval");
                DynamicObject approvalObj = BusinessDataServiceHelper.loadSingle(approval.getPkValue(),
                        approval.getDynamicObjectType().getName());
                QFilter qFilter = new QFilter("project.id", QCP.equals, approvalObj.getDynamicObject("project").get("id"));
                qFilter.and(new QFilter("year", QCP.equals, approvalObj.get("year")));
                approvalObj.get("isvalid");
                qFilter.and(new QFilter("isvalid", QCP.equals, true));
                DynamicObjectCollection ids = QueryServiceHelper.query(approval.getDynamicObjectType().getName(), "id, billno",
                        new QFilter[]{qFilter});
                if (ids == null || ids.size() == 0) {
                    this.getView().showTipNotification("未找到有效版本的项目支出预算,反写项目立项单失败,请检查！");
                    return;
                } else if (ids.size() != 1) {
                    this.getView().showTipNotification("该项目支出预算有多个有效版本,反写项目立项单失败,请检查！");
                    return;
                }
                // 获取最新有效版本的项目支出预算
                DynamicObject business = BusinessDataServiceHelper.loadSingle(ids.get(0).get("id"),
                        approval.getDynamicObjectType().getName());
                //获取项目支出预算项的分录数据
                DynamicObjectCollection treeentryentity = business.getDynamicObjectCollection("treeentryentity");
                String group = business.getString("group.number");
                String parent = business.getString("group.parent.number");
                DynamicObjectCollection entryentity = this.getModel().getEntryEntity("entryentity");
                Map<String, BigDecimal> maps;
                if (!"106".equals(parent)) {
                    switch (group) {
                        case "10201":
                        case "10301":
                        case "10302":
                        case "10303":
                        case "10304":
                        case "10305":
                        case "10401":
                        case "10601":
                            maps = entyNumTaxamount(entryentity, "amount");
                            break;
                        default:
                            maps = entyNumTaxamount(entryentity, "taxamount");
                            break;
                    }
                } else {
                    maps = entyNumTaxamount(entryentity, "amount");
                }
                for (String key : maps.keySet()) {
                    BigDecimal big = maps.get(key);
                    DynamicObject budget = BusinessDataServiceHelper.loadSingle(key, "pmas_projectbudget");
                    for (DynamicObject tre : treeentryentity) {
                        //项目预算项的名称
                        String budgetName = tre.getString("budgetitemname");
                        if (StringUtils.equals(budget.getString("name"), budgetName)) {
                            //获取本阶段余额
                            BigDecimal budgetamoney = tre.getBigDecimal("budgetamoney");
                            switch (operateKey) {
                                case "audit":
                                    BigDecimal subtract = budgetamoney.subtract(big);
                                    tre.set("budgetamoney", subtract);
                                    break;
                                case "invalid":
                                case "unaudit":
                                    BigDecimal ract = budgetamoney.add(big);
                                    tre.set("budgetamoney", ract);
                                    break;
                            }
                            break;
                        }
                    }
                }
                SaveServiceHelper.update(business);
            }
        }
    }

    @Override
    public void beforeF7Select(BeforeF7SelectEvent event) {
        String name = event.getProperty().getName();
        if ("approvalbudget".equals(name)) {
            DynamicObject approval = (DynamicObject) this.getModel().getValue("pro_approval");
            if (approval == null) {
                event.setCancel(true);
                this.getView().showTipNotification(ResManager.loadKDString("请先选择项目。", "SrcDemandFormPlugin_1", "pmgt-pmct-formplugin",
                        new Object[0]));
                return;
            }
            DynamicObject outbudget = BusinessDataServiceHelper.loadSingle(approval.getPkValue(), "pmas_outbudget");
            DynamicObject project = outbudget.getDynamicObject("project");
            List<QFilter> qFilters = new ArrayList();
            QFilter projectFilter = new QFilter("project", "=", project.getPkValue());
            QFilter sourceTypeFilter = new QFilter("sourcetype", "=", "OUT");
            qFilters.add(projectFilter);
            qFilters.add(sourceTypeFilter);
            DynamicObject[] budgetItems = BusinessDataServiceHelper.load("pmas_projectbudget", "parent,name",
                    (QFilter[]) qFilters.toArray(new QFilter[0]));
            if (budgetItems.length == 0) {
                event.setCancel(true);
                this.getView().showTipNotification(ResManager.loadKDString("当前项目不存在预算项。", "SrcDemandFormPlugin_2", "pmgt-pmct-formplugin"
                        , new Object[0]));
                return;
            }

            List<Object> ids = (List) Arrays.stream(budgetItems).filter((budgetItem) -> {
                QFilter parentFilter = new QFilter("parent", "=", budgetItem.getLong("id"));
                DynamicObject[] children = BusinessDataServiceHelper.load("pmas_projectbudget", "", new QFilter[]{parentFilter});
                return children == null || children.length == 0;
            }).map(DataEntityBase::getPkValue).collect(Collectors.toList());
            QFilter filter = new QFilter("id", "in", ids);
            ListShowParameter listShowParameter = (ListShowParameter) event.getFormShowParameter();
            List<Map<String, Object>> list = new ArrayList();
            DynamicObjectCollection treee = outbudget.getDynamicObjectCollection("treeentryentity");
            for (int i = 0; i < budgetItems.length; i++) {
                Map map = new HashMap();
                String budgetName = budgetItems[i].getString("name");
                for (DynamicObject tre : treee) {
                    String budgetitemname = tre.getString("budgetitemname");
                    if (StringUtils.equals(budgetName, budgetitemname)) {
                        //预算项总金额
                        map.put("budgetamount", tre.getBigDecimal("budgetamount"));
                        //剩余金额
                        map.put("remainamt", tre.getBigDecimal("budgetamoney"));
                        map.put("descrip", tre.getString("descriptionentry"));//备注
                    }
                }

                list.add(map);
            }
            listShowParameter.setCloseCallBack(new CloseCallBack(this, "update"));
            listShowParameter.setCustomParam("list", list);
            listShowParameter.getListFilterParameter().getQFilters().add(filter);
        }
        if (name.equals("pro_approval")) {
            DynamicObject org_tmp = (DynamicObject) this.getModel().getValue("org_tmp");
            QFilter qFilter = new QFilter("org.id", QCP.equals, org_tmp.getPkValue());

            event.setCustomQFilters(Arrays.asList(qFilter.toArray()));
        }
    }

    @Override
    public void closedCallBack(ClosedCallBackEvent e) {
        if (e.getReturnData() != null && StringUtils.equals("update", e.getActionId())) {
            List list = (List) e.getReturnData();
            logger.info("SrcDemandFormPlugin.closedCallBack.list:{}", list);
            DynamicObject projectbudget = BusinessDataServiceHelper.loadSingle(list.get(0).toString(), "pmas_projectbudget");
            DynamicObject project = projectbudget.getDynamicObject("project");
            String pkId = projectbudget.getPkValue().toString();
            logger.info("SrcDemandFormPlugin.closedCallBack.projectbudget:{}", projectbudget);

            EntryGrid entryGrid = this.getControl("entryentity");
            int[] selectRows = entryGrid.getSelectRows();
            this.getModel().setValue("approvalbudget", projectbudget, selectRows[0]);
            DynamicObject approval = (DynamicObject) this.getModel().getValue("pro_approval");
            DynamicObject appro = BusinessDataServiceHelper.loadSingle(approval.getPkValue(), "pmas_outbudget");

            DynamicObject outbudget = BusinessDataServiceHelper.loadSingle("pmas_outbudget", "id",
                    new QFilter[]{new QFilter("project.id", QCP.equals, project.getPkValue())
                            .and(new QFilter("isvalid", QCP.equals, true))
                            .and(new QFilter("year", QCP.equals,appro.getDate("year")))});
            DynamicObject pmas = BusinessDataServiceHelper.loadSingle(outbudget.getPkValue(), "pmas_outbudget");
            logger.info("SrcDemandFormPlugin.closedCallBack.pmas:{}", pmas);

            DynamicObjectCollection treeentr = pmas.getDynamicObjectCollection("treeentryentity");
            for (DynamicObject tre : treeentr) {
                DynamicObject projectbudgetitem = tre.getDynamicObject("projectbudgetitem");
                logger.info("SrcDemandFormPlugin.closedCallBack.projectbudgetitem:{}", projectbudgetitem);
                if (StringUtils.equals(pkId, projectbudgetitem.getPkValue().toString())) {
                    BigDecimal amoney = tre.getBigDecimal("budgetamoney");//余额
                    logger.info("SrcDemandFormPlugin.closedCallBack.amoney:{}", amoney);
                    this.getModel().setValue("budgetmoney", amoney, selectRows[0]);
                    break;
                }
            }

            for (int i = 1; i < list.size(); i++) {
                DynamicObject projects = BusinessDataServiceHelper.loadSingle(list.get(i).toString(), "pmas_projectbudget");
                String proPkId = projects.getPkValue().toString();
                logger.info("SrcDemandFormPlugin.closedCallBack.projects:{}", projects);
                int index = this.getModel().createNewEntryRow("entryentity");
                this.getModel().setValue("approvalbudget", projects, index);
                for (DynamicObject tre : treeentr) {
                    String budgetitemname = tre.getString("projectbudgetitem");
                    logger.info("SrcDemandFormPlugin.closedCallBack.budgetitemname:{}", budgetitemname);
                    if (StringUtils.equals(proPkId, budgetitemname)) {
                        BigDecimal amoney = tre.getBigDecimal("budgetamoney");//余额
                        logger.info("SrcDemandFormPlugin.closedCallBack.amoney:{}", amoney);

                        this.getModel().setValue("budgetmoney", amoney, index);
                        break;
                    }
                }

            }
        }
    }

    private Map<String, Map<String, BigDecimal>> entyNumMoney(DynamicObjectCollection entryentitys, DynamicObject dat,
                                                              DynamicObjectCollection entrs) {
        Map<String, Map<String, BigDecimal>> maps = new HashMap();
        if (dat != null) {
            DynamicObject single = BusinessDataServiceHelper.loadSingle(dat.getPkValue(), dat.getDynamicObjectType().getName());
            String name = single.getString("name");
            Map map = new HashMap();
            for (DynamicObject ent : entrs) {
                if (StringUtils.equals(name, ent.getString("budgetitemname"))) {
                    //本阶段余额
                    map.put("remaining", ent.getBigDecimal("budgetamoney"));
                    maps.put(name, map);
                }
            }
        }
        for (int i = 0; i < entryentitys.size(); i++) {
            DynamicObject enty = entryentitys.get(i);
            DynamicObject approvalbudget = enty.getDynamicObject("approvalbudget");
            if (approvalbudget == null) {
                continue;
            }
            DynamicObject single = BusinessDataServiceHelper.loadSingle(approvalbudget.getPkValue(),
                    approvalbudget.getDynamicObjectType().getName());
            String name = single.getString("name");
            Map map = new HashMap();
            for (DynamicObject ent : entrs) {
                if (StringUtils.equals(name, ent.getString("budgetitemname"))) {
                    //本阶段余额
                    map.put("remaining", ent.getBigDecimal("budgetamoney"));
                    maps.put(name, map);
                    break;
                }
            }
        }
        return maps;

    }

    //根据预算项计算在分录中所有的价税合计/未税金额集合
    private Map<String, BigDecimal> entyNumTaxamount(DynamicObjectCollection entryentity, String txt) {
        Map<String, BigDecimal> maps = new HashMap<>();
        for (int i = 0; i < entryentity.size(); i++) {
            DynamicObject entr = entryentity.get(i);
            BigDecimal taxamount = entr.getBigDecimal(txt);//价税合计
            DynamicObject approvalbudget = entr.getDynamicObject("approvalbudget");
            if (approvalbudget != null) {
                String id = approvalbudget.getPkValue().toString();
                BigDecimal big = maps.get(id);
                if (big != null) {
                    BigDecimal budge = big.add(taxamount);
                    maps.put(id, budge);
                } else {
                    BigDecimal balance = entr.getBigDecimal(txt);
                    maps.put(id, balance);
                }
            }
        }
        return maps;
    }


    private BigDecimal entyConutTaxamount(DynamicObjectCollection entryentity, String txt) {
        BigDecimal bigDecimal = new BigDecimal("0");
        for (int i = 0; i < entryentity.size(); i++) {
            DynamicObject ent = entryentity.get(i);
            bigDecimal = bigDecimal.add(ent.getBigDecimal(txt));
        }
        return bigDecimal;
    }

    @Override
    public void afterBindingData(AfterBindingDataEvent event) {
    }


}
